1 - Análise exploratória de dados#
Este material foi adaptado de [MagalhaesdL02] e [Mar15].
Definições básicas#
O que é estatística?\(^1\)#
Estatística é um conjunto de técnicas para, sistematicamente:
Planejar a coleta de dados oriundos de estudos ou experimentos, realizados em qualquer área do conhecimento;
Descrever, analisar e interpretar dados;
Extrair informações para subsidiar decisões;
Avaliar evidências empíricas sob hipóteses de interesse.
\(^1\) http://www.leg.ufpr.br/
Exemplos de aplicações:#
Opinião da população brasileira sobre o novo governo.
Avaliar a efetividade de uma nova droga para a cura do câncer.
Entender os hábitos de compra dos clientes de uma loja virtual.
Recomendação personalizada de produtos.
Comparar a produtividade da soja sob diferentes formas de cultivo, adubação, etc.
Conceitos fundamentais#
População: Conjunto de todos os elementos sob investigação.
Amostra: Subconjunto da população.
Variável de interesse: característica a ser observada em cada indivíduo da amostra.
Divisões básicas da estatística#
Exemplo 1: Opinião da população brasileira sobre o novo governo.
População: Todos os habitantes do Brasil? outras opções?
Amostra: Algum subconjunto da população. Qualquer um será? Como selecionar?
Variável de interesse: Opinião sobre o novo governo. Como medir isso? Gosta? sim ou não.
Exemplo 2: Avaliar a efetividade de uma nova droga para a cura do câncer.
População: Todos os seres humanos? Apenas os já doentes? Como levar em conta questões de raça, culturas, etc …
Amostra: E agora?
Variável de interesse: Curou ou não curou? Será que isso é possível?
Exemplo 3: Entender os hábitos de compra dos clientes de uma loja virtual.
População: Todos os clientes da loja virtual.
Amostra: Preciso de amostra?
Variável de interesse: E agora? Como caracterizar hábito de compra?
Desenho de estudos#
Estudos caso-controle#
De uma mesma população são selecionadas amostras de indivíduos portadores de uma condição (casos) e outra de indivíduos não portadores (controle). Se há maior frequência de exposição a uma situação entre os indivíduos portadores, temos um indício de que a exposição está relacionada à condição de interesse.
Estudos transversais#
Seleciona-se uma amostra da população em questão, e posteriormente, verificamos quem é portador ou não da característica de interesse (por exemplo, doença). Objetiva-se obter uma estimativa da proporção de pessoas portadoras da característica. Como todas as informações da amostra são obtidas em um mesmo instante, pode ser difícil entender se a característica de interesse surgiu antes ou depois da exposição.
Estudos de coorte#
Os indivíduos amostados são classificados como expostos ou não a uma situação que pode (ou não) ocasionar um evento específico (como uma doença). Esses individuos são acompanhados durante um período, e se ocorrer um mais eventos entre indivíduos expostos, temos evidências que a exposição pode ocasionar aquele evento.
Estudos de intervenção#
Objetiva-se administrar um tipo de intervenção capaz de alterar algum aspecto dos indivíduos, como o estado de saúde. Os estudos podem ser caracterizados como profiláticos ou terapêuticos. Um tipo de intervenção comum é o ensaio controlado aleatorizado, em que os indivíduos elegíveis ao estudo são divididos ao acaso em dois ou mais grupos. O grupo que não recebe a intervenção, ou tratamento, é geralmente denominado grupo controle. Outro tipo de estudo de intervenção é chamado de ensaio de não superioridade, cujo objetivo é entender se a intervenção estudada é tão benéfica quanto outra tradicionalmente utillizada no tratamento de uma condição.
Planejamento da coleta dos dados#
Coleta de dados por amostragem
Definição da população e característica de interesse.
Definição do plano amostral:
Aleatória simples (com ou sem reposição) ou sistemática;
Estratificada, por estratos da população (segundo uma característica);
Conglomerados, por grupos de indivíduos da população (subpopulações);
Amostragem complexa (combina anteriores).
Divisões essenciais em Estatı́stica e seus principais objetivos.#
Estatı́stica descritiva ou exploratória:
Consistência dos dados e interpretações iniciais.
Visualização dos dados e relações entre variáveis.
Probabilidade:
Fornece ferramentas para lidar/quantificar incerteza.
Inferência estatı́stica:
Estimação de quantidades desconhecidas.
Formular e testar hipóteses.
Extrapolar para a população resultados obtidos na amostra.
Exemplo#
Pesquisa foi realizada com alunos. Variáveis:
Id: identificação do aluno; Turma: A ou B;
Sexo: feminino (F) ou masculino (M);
Idade: em anos; Alt: altura em metros;
Peso: em quilogramas; Filhos: nº de filhos na famı́lia;
Fuma: hábito de fumar: sim (S) ou não (N);
Toler: tolerância ao cigarro: (I) indiferente; (P) incomoda pouco; (M) incomoda muito;
Exerc.: horas de atividade fı́sica, por semana;
Cine: nº. de vezes que vai ao cinema por semana;
OpCine: opinião a respeito das salas de cinema na cidade: (B) regular a boa; (M) muito boa;
TV: horas gastas assistindo TV, por semana;
OpTV: opinião a respeito da qualidade da programação na TV: (R) ruim; (M) média; (B) boa; (N) não sabe.
Organização dos dados#
A partir de um conjunto de dados coletado, a questão é:
Como extrair informações a respeito de uma ou mais caracterı́sticas de interesse?
Basicamente temos duas opções:
Tabelas de frequência;
Gráficos.
O importante é levar em consideração a natureza dos dados.
Tipos de variáveis#
Organização de Dados#
Uma tı́pica tabela de dados brutos contém:
Variáveis (caracterı́sticas, medições, etc) nas colunas.
Sujeito (indivı́duo, objetos, etc) nas linhas.
Tipos de variáveis:
Qualitativa nominal: Turma, Sexo, Fuma.
Qualitativa ordinal: Toler, OpCine, OpTV.
Quantitativa discreta: Idade, Filhos, Exerc, Cine, TV.
Quantitativa contı́nua: Alt, Peso.
Tabelas de frequência#
A tabela de dados brutos pode ser muito longa, portanto será difı́cil extrair alguma informação.
As tabelas de frequência ajudam a resumir a informação da variável de interesse.
Vamos usar 3 tipos de frequência:
Frequência absoluta: contagem de cada valor observado. Representado por \(n_i\) o número de indivı́duos com a caracterı́stica i.
Frequência relativa: número de indivı́duos com a caracterı́stica i dividido pelo total de indivı́duos n, ou seja \(f_i = \frac{n_i}{n}\).
Frequência acumulada: frequência (absoluta ou relativa) acumulada até um certo valor, obtida pela soma das frequências de todos os valores da variável, menores ou iguais ao valor considerado.
Show code cell source
# HIDE CODE
import pandas as pd
df = pd.read_excel('questionario.xls')
df.head()
| Id | Turma | Sexo | Idade | Alt | Peso | Filhos | Fuma | Toler | Exerc | Cine | OpCine | TV | OpTV | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | A | F | 17 | 1.60 | 60.5 | 2 | NAO | P | 0 | 1 | B | 16 | R |
| 1 | 2 | A | F | 18 | 1.69 | 55.0 | 1 | NAO | M | 0 | 1 | B | 7 | R |
| 2 | 3 | A | M | 18 | 1.85 | 72.8 | 2 | NAO | P | 5 | 2 | M | 15 | R |
| 3 | 4 | A | M | 25 | 1.85 | 80.9 | 2 | NAO | P | 5 | 2 | B | 20 | R |
| 4 | 5 | A | F | 19 | 1.58 | 55.0 | 1 | NAO | M | 2 | 2 | B | 5 | R |
Tabela de frequência - qualitativa nominal#
Show code cell source
# HIDE CODE
df['Turma'].value_counts()
Turma
A 26
B 24
Name: count, dtype: int64
Show code cell source
# HIDE CODE
df['Turma'].value_counts()/50
Turma
A 0.52
B 0.48
Name: count, dtype: float64
Show code cell source
# HIDE CODE
tab_fr = pd.concat([df['Turma'].value_counts(),
df['Turma'].value_counts()/50],
axis=1)
tab_fr.columns = ['Frequência absoluta', 'Frequência relativa']
tab_fr
| Frequência absoluta | Frequência relativa | |
|---|---|---|
| Turma | ||
| A | 26 | 0.52 |
| B | 24 | 0.48 |
Neste caso não faz sentido usar frequência acumulada.
Tabela de frequência - qualitativa ordinal#
Show code cell source
# HIDE CODE
tab_fr = pd.concat([df['OpTV'].value_counts(),
df['OpTV'].value_counts()/50,
(df['OpTV'].value_counts()/50).cumsum()],
axis=1)
tab_fr.columns = ['Frequência absoluta', 'Frequência relativa', 'Frequência acumulada']
tab_fr
| Frequência absoluta | Frequência relativa | Frequência acumulada | |
|---|---|---|---|
| OpTV | |||
| R | 39 | 0.78 | 0.78 |
| N | 7 | 0.14 | 0.92 |
| B | 3 | 0.06 | 0.98 |
| M | 1 | 0.02 | 1.00 |
Tabela de frequência - quantitativa discreta#
Show code cell source
# HIDE CODE
tab_fr = pd.concat([df['Idade'].value_counts(),
df['Idade'].value_counts()/50,
(df['Idade'].value_counts()/50).cumsum()],
axis=1)
tab_fr.columns = ['Frequência absoluta', 'Frequência relativa', 'Frequência acumulada']
tab_fr.sort_index(inplace=True)
tab_fr
| Frequência absoluta | Frequência relativa | Frequência acumulada | |
|---|---|---|---|
| Idade | |||
| 17 | 9 | 0.18 | 0.62 |
| 18 | 22 | 0.44 | 0.44 |
| 19 | 7 | 0.14 | 0.76 |
| 20 | 4 | 0.08 | 0.84 |
| 21 | 3 | 0.06 | 0.90 |
| 23 | 2 | 0.04 | 0.98 |
| 24 | 1 | 0.02 | 1.00 |
| 25 | 2 | 0.04 | 0.94 |
Tabela de frequência - quantitativa contı́nua#
No caso de quantitativas contı́nuas não faz sentido contar cada valor pois podem existir muitos (potencialmente infinito).
A solução é criar classes ou faixas de valores, e contar o número de ocorrências dentro destas classes.
Para definir as classes:
Defina a amplitude da classe, de maneira que se obtenham de 5 a 8 classes (de mesma amplitude).
Identifique os valores máximo e mı́nimo da variável e construa as classes de maneira que inclua todos os valores.
As classes de valores podem seguir um dos formatos:
Show code cell source
# HIDE CODE
%%capture
from matplotlib import pyplot as plt
h = plt.hist(df['Peso'], bins=10)
UsageError: Line magic function `%%capture` not found.
h
(array([ 7., 8., 15., 6., 2., 5., 1., 2., 3., 1.]),
array([44. , 49.1, 54.2, 59.3, 64.4, 69.5, 74.6, 79.7, 84.8, 89.9, 95. ]),
<BarContainer object of 10 artists>)
Show code cell source
# HIDE CODE
%%capture
h = plt.hist(df['Peso'], bins=[40, 50, 60, 70, 80, 90, 100])
Show code cell source
# HIDE CODE
pd.DataFrame([h[0], h[0]/50, (h[0]/50).cumsum()],
index=['Frequência absoluta', 'Frequência relativa', 'Frequência acumulada']).T
| Frequência absoluta | Frequência relativa | Frequência acumulada | |
|---|---|---|---|
| 0 | 8.0 | 0.16 | 0.16 |
| 1 | 22.0 | 0.44 | 0.60 |
| 2 | 8.0 | 0.16 | 0.76 |
| 3 | 6.0 | 0.12 | 0.88 |
| 4 | 5.0 | 0.10 | 0.98 |
| 5 | 1.0 | 0.02 | 1.00 |
Tabela de frequência - quantitativa discreta (muitos valores)#
Considerando a variável TV.
Apesar de ser discreta, o número de valores únicos é muito grande e não seria útil contar as frequências de cada valor.
Neste caso, utiliza-se o mesmo procedimento usado para quantitativas contı́nuas
Foram construı́das 6 classes de amplitude \(6^3\).
Show code cell source
# HIDE CODE
%%capture
h = plt.hist(df['TV'], bins=[0, 6, 12, 18, 24, 30, 36])
Show code cell source
# HIDE CODE
pd.DataFrame([h[0], h[0]/50, (h[0]/50).cumsum()],
index=['Frequência absoluta', 'Frequência relativa', 'Frequência acumulada']).T
| Frequência absoluta | Frequência relativa | Frequência acumulada | |
|---|---|---|---|
| 0 | 14.0 | 0.28 | 0.28 |
| 1 | 17.0 | 0.34 | 0.62 |
| 2 | 11.0 | 0.22 | 0.84 |
| 3 | 4.0 | 0.08 | 0.92 |
| 4 | 3.0 | 0.06 | 0.98 |
| 5 | 1.0 | 0.02 | 1.00 |
Representação gráfica#
Podemos visualizar as tabelas através de gráficos.
Existe um tipo de gráfico adequado para cada tipo de variável.
Cuidado deve ser tomado com representações visuais pois um gráfico desproporcional pode gerar interpretações distorcidas.
As principais representações gráficas são:
Diagrama circular (setores ou “pizza”);
Gráfico de barras;
Histogramas;
Boxplots.
Diagrama circular#
Adequado para variáveis qualitativas nominal e ordinal.
O uso deste tipo de gráfico deve ser evitado, pois pode ser de difı́cil interpretação.
Show code cell source
# HIDE CODE
df['Toler'].value_counts()
Toler
P 21
M 19
I 10
Name: count, dtype: int64
Show code cell source
# HIDE CODE
df['Toler'].value_counts().index.values
array(['P', 'M', 'I'], dtype=object)
Show code cell source
# HIDE CODE
plt.pie(df['Toler'].value_counts(),
labels=df['Toler'].value_counts().index.values,
autopct='%1.1f%%')
([<matplotlib.patches.Wedge at 0x79f2908faca0>,
<matplotlib.patches.Wedge at 0x79f2908fabe0>,
<matplotlib.patches.Wedge at 0x79f2911fef10>],
[Text(0.27355891977302554, 1.065441465972024, 'P'),
Text(-0.8475646353272168, -0.7011663061946446, 'M'),
Text(0.8899186272232006, -0.646563869173939, 'I')],
[Text(0.14921395623983208, 0.5811498905301948, '42.0%'),
Text(-0.4623079829057546, -0.3824543488334425, '38.0%'),
Text(0.4854101603035639, -0.35267120136760305, '20.0%')])
Gráfico de barras#
Adequado para variáveis qualitativas nominal/ordinal e quantitativa discreta (poucos valores distintos).
Podem ser usadas as frequências absolutas ou relativas.
Show code cell source
# HIDE CODE
plt.bar(df['Toler'].value_counts().index.values,
df['Toler'].value_counts())
<BarContainer object of 3 artists>
Show code cell source
# HIDE CODE
plt.bar(df['Toler'].value_counts().index.values,
df['Toler'].value_counts()/50)
<BarContainer object of 3 artists>
Show code cell source
# HIDE CODE
plt.rcParams["figure.figsize"] = (10,8)
fig, (ax1, ax2) = plt.subplots(1, 2)
fig.suptitle('Subplots combinados horizontalmente')
ax1.bar(df['Toler'].value_counts().index.values,
df['Toler'].value_counts())
ax1.set_ylabel('Frequência absoluta')
ax2.bar(df['Toler'].value_counts().index.values,
df['Toler'].value_counts()/50)
ax2.set_ylabel('Frequência relativa')
Text(0, 0.5, 'Frequência relativa')
Show code cell source
# HIDE CODE
plt.rcParams["figure.figsize"] = plt.rcParamsDefault["figure.figsize"]
Show code cell source
# HIDE CODE
pd.crosstab(df['Toler'], df['Turma']).plot(kind='bar')
<Axes: xlabel='Toler'>
Histograma#
Adequado para quantitativa contı́nua.
Altura de cada retângulo é a densidade definida pelo quociente da área pela amplitude da faixa, \(h = \frac{f_i}{AMP}\).
Show code cell source
# HIDE CODE
import numpy as np
fig, ax = plt.subplots()
ax.hist(df['Peso'], bins=[40, 50, 60, 70, 80, 90, 100], weights=np.zeros_like(df['Peso']) + 1. / df['Peso'].size)
ax.set_ylabel('Frequência relativa')
Text(0, 0.5, 'Frequência relativa')
Show code cell source
# HIDE CODE
fig, ax = plt.subplots()
ax.hist(df['Peso'], bins=[40, 50, 60, 70, 80, 90, 100], density=True)
ax.set_ylabel('Densidade')
Text(0, 0.5, 'Densidade')
Mediana e quartis#
Mediana: valor da variável que divide o conjunto de dados ordenado em dois subgrupos de mesmo tamanho.
Quartis: valores da variável que divide o conjunto de dados ordenados em quatro subgrupos de mesmo tamanho.
Posição dos quartis:
Q1 = 0.25 · (N + 1) e arredonde.
Q2 = média dos valores nas posições (N/2) e (N/2) + 1 se N par e
Q2 = (N + 1)/2 se N ı́mpar.
Q3 = 0.75 · (N + 1) e arredonde.
Exemplo: Conside o conjunto de dados: 8.43(1), 8.65(2), 9.96(3), 10.91(6), 10.46(4) e 10.83(5).
Q1 = 0.25 · 7 = 1.75 ≈ 2, ou seja 8.65.
Q2 = média dos valores nas posições 3 e 4, ou seja, (9.96 + 10.46)/2 = 10.21.
Q3 = 0.75 · 7 = 5.25 ≈ 5, ou seja, 10.83.
Boxplots#
Excelente para explorar relações entre qualitativas e contı́nuas.
Show code cell source
# HIDE CODE
df.boxplot(['Peso'])
<Axes: >
Show code cell source
# HIDE CODE
# Como obter os quartis representados no boxplot
df['Peso'].quantile([.25, .5, .75])
0.25 52.125
0.50 58.000
0.75 67.875
Name: Peso, dtype: float64
Show code cell source
# HIDE CODE
# Descrever os componentes principais do boxplot
plt.boxplot(df['Peso'])
plt.hlines(58, 0.5, 1.5, linestyles='dashed', colors='orange')
plt.hlines(52.125, 0.5, 1.5, linestyles='dashed', colors='blue')
plt.hlines(67.875, 0.5, 1.5, linestyles='dashed', colors='red')
<matplotlib.collections.LineCollection at 0x79f25829a490>
Show code cell source
# HIDE CODE
# a altura da caixa é dada pela
# amplitude interquartil (AIQ) ou do inglês (IQR)
iqr = 67.875-52.125
# Para os limites superior e inferior, utilizamos
# os pontos dos dados mais próximos das fórmulas abaixo
# Q3+1.5*IQR
whigh = df.loc[df['Peso']<= (67.875+1.5*iqr), 'Peso'].max()
# Q1-1.5*IQR
wlow = df.loc[df['Peso']>= (52.125-1.5*iqr), 'Peso'].min()
Show code cell source
# HIDE CODE
# Representação dos limites inferior e superior
plt.boxplot(df['Peso'])
plt.hlines(whigh, 0.5, 1.5, linestyles='dashed', colors='orange')
plt.hlines(wlow, 0.5, 1.5, linestyles='dashed', colors='orange')
<matplotlib.collections.LineCollection at 0x79f2581b51c0>
Show code cell source
# HIDE CODE
import seaborn as sns
sns.boxplot(y=df["Peso"])
<Axes: ylabel='Peso'>
Show code cell source
# HIDE CODE
fig, ax = plt.subplots()
ax.boxplot(df.loc[df['Turma']=='A', 'Peso'], patch_artist=True, showmeans=True, positions=[1])
ax.boxplot(df.loc[df['Turma']=='B', 'Peso'], patch_artist=True, showmeans=True, positions=[2])
ax.autoscale()
ax.set(xticks=[1,2], xticklabels=['A','B'])
[[<matplotlib.axis.XTick at 0x79f258b761f0>,
<matplotlib.axis.XTick at 0x79f258b761c0>],
[Text(1, 0, 'A'), Text(2, 0, 'B')]]
Show code cell source
# HIDE CODE
sns.boxplot(data=df, x="Turma", y="Peso", hue="Turma")
<Axes: xlabel='Turma', ylabel='Peso'>
Diagrama de dispersão#
Adequado para explorar a relação entre variáveis quantitativas.
Show code cell source
# HIDE CODE
# prompt: genetare scatter plot of weigth and height
plt.scatter(df['Peso'], df['Alt'])
plt.xlabel('Peso')
plt.ylabel('Altura')
plt.title('Gráfico de Dispersão: Peso vs Altura')
plt.show()
Exemplo complexo#
Vamos utilizar os dados do portal Gapminder para mostrar o diagrama de bolhas (bubble plot), assim como a criação de um gráfico dinâmico com uso de inteligência artificial.
import pandas as pd
from IPython.display import display, HTML
pop = pd.read_csv('pop.csv')
pop.head()
| country | 1800 | 1801 | 1802 | 1803 | 1804 | 1805 | 1806 | 1807 | 1808 | ... | 2091 | 2092 | 2093 | 2094 | 2095 | 2096 | 2097 | 2098 | 2099 | 2100 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Afghanistan | 3.28M | 3.28M | 3.28M | 3.28M | 3.28M | 3.28M | 3.28M | 3.28M | 3.28M | ... | 124M | 125M | 126M | 126M | 127M | 128M | 128M | 129M | 130M | 130M |
| 1 | Angola | 1.57M | 1.57M | 1.57M | 1.57M | 1.57M | 1.57M | 1.57M | 1.57M | 1.57M | ... | 139M | 140M | 142M | 143M | 144M | 145M | 147M | 148M | 149M | 150M |
| 2 | Albania | 400k | 402k | 404k | 405k | 407k | 409k | 411k | 413k | 414k | ... | 1.34M | 1.32M | 1.3M | 1.29M | 1.27M | 1.25M | 1.23M | 1.22M | 1.2M | 1.18M |
| 3 | Andorra | 2650 | 2650 | 2650 | 2650 | 2650 | 2650 | 2650 | 2650 | 2650 | ... | 52.8k | 52.1k | 51.5k | 50.8k | 50.2k | 49.6k | 49k | 48.4k | 47.8k | 47.2k |
| 4 | UAE | 40.2k | 40.2k | 40.2k | 40.2k | 40.2k | 40.2k | 40.2k | 40.2k | 40.2k | ... | 24.1M | 24.3M | 24.5M | 24.7M | 25M | 25.2M | 25.4M | 25.7M | 25.9M | 26.1M |
5 rows × 302 columns
ch_wom = pd.read_csv('children_per_woman_total_fertility.csv')
ch_wom.head()
| country | 1800 | 1801 | 1802 | 1803 | 1804 | 1805 | 1806 | 1807 | 1808 | ... | 2091 | 2092 | 2093 | 2094 | 2095 | 2096 | 2097 | 2098 | 2099 | 2100 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Afghanistan | 7.00 | 7.00 | 7.00 | 7.00 | 7.00 | 7.00 | 7.00 | 7.00 | 7.00 | ... | 2.16 | 2.14 | 2.13 | 2.12 | 2.11 | 2.10 | 2.09 | 2.08 | 2.07 | 2.06 |
| 1 | Angola | 6.93 | 6.93 | 6.93 | 6.93 | 6.93 | 6.93 | 6.93 | 6.94 | 6.94 | ... | 2.24 | 2.23 | 2.22 | 2.21 | 2.20 | 2.18 | 2.17 | 2.16 | 2.15 | 2.14 |
| 2 | Albania | 4.60 | 4.60 | 4.60 | 4.60 | 4.60 | 4.60 | 4.60 | 4.60 | 4.60 | ... | 1.48 | 1.48 | 1.49 | 1.49 | 1.49 | 1.49 | 1.49 | 1.49 | 1.50 | 1.49 |
| 3 | Andorra | 2.11 | 2.11 | 2.11 | 2.11 | 2.11 | 2.11 | 2.11 | 2.11 | 2.11 | ... | 1.40 | 1.40 | 1.40 | 1.40 | 1.40 | 1.40 | 1.40 | 1.41 | 1.41 | 1.41 |
| 4 | UAE | 6.94 | 6.94 | 6.94 | 6.94 | 6.94 | 6.94 | 6.94 | 6.94 | 6.94 | ... | 1.44 | 1.44 | 1.45 | 1.45 | 1.45 | 1.45 | 1.45 | 1.46 | 1.46 | 1.46 |
5 rows × 302 columns
gdp_pcap = pd.read_csv('gdp_pcap.csv')
gdp_pcap.head()
| country | 1800 | 1801 | 1802 | 1803 | 1804 | 1805 | 1806 | 1807 | 1808 | ... | 2091 | 2092 | 2093 | 2094 | 2095 | 2096 | 2097 | 2098 | 2099 | 2100 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Afghanistan | 481 | 481 | 481 | 481 | 481 | 481 | 481 | 481 | 481 | ... | 4680 | 4790 | 4910 | 5020 | 5140 | 5260 | 5380 | 5510 | 5640 | 5780 |
| 1 | Angola | 373 | 374 | 376 | 378 | 379 | 381 | 383 | 385 | 386 | ... | 24.5k | 25k | 25.6k | 26.1k | 26.6k | 27.1k | 27.7k | 28.2k | 28.8k | 29.3k |
| 2 | Albania | 469 | 471 | 472 | 473 | 475 | 476 | 477 | 479 | 480 | ... | 54.5k | 55.1k | 55.7k | 56.3k | 56.9k | 57.4k | 58k | 58.6k | 59.2k | 59.8k |
| 3 | Andorra | 1370 | 1370 | 1370 | 1380 | 1380 | 1380 | 1390 | 1390 | 1390 | ... | 79.9k | 80.2k | 80.4k | 80.7k | 81k | 81.3k | 81.5k | 81.8k | 82k | 82.3k |
| 4 | UAE | 1140 | 1150 | 1150 | 1150 | 1160 | 1160 | 1170 | 1170 | 1180 | ... | 92.6k | 92.6k | 92.6k | 92.7k | 92.7k | 92.7k | 92.8k | 92.8k | 92.8k | 92.9k |
5 rows × 302 columns
pop.shape[1]==ch_wom.shape[1]==gdp_pcap.shape[1]
True
pop.loc[(pop['country']=='China'), '2020']
32 1.43B
Name: 2020, dtype: object
# Prepare data for the plot
year = '2020'
data2020 = pop[['country', year]].merge(
ch_wom[['country', year]], on='country'
).merge(
gdp_pcap[['country', year]], on='country'
)
data2020.index = data2020['country']
data2020.drop(columns=['country'], inplace=True)
data2020.head()
| 2020_x | 2020_y | 2020 | |
|---|---|---|---|
| country | |||
| Afghanistan | 39.1M | 5.15 | 1970 |
| Angola | 33.5M | 5.37 | 6030 |
| Albania | 2.87M | 1.37 | 13.3k |
| Andorra | 77.4k | 1.03 | 49.7k |
| UAE | 9.45M | 1.29 | 67.4k |
data2020.loc[['China', 'India']]
| 2020_x | 2020_y | 2020 | |
|---|---|---|---|
| country | |||
| China | 1.43B | 1.24 | 16.3k |
| India | 1.4B | 2.05 | 6140 |
data2020.columns = ['pop', 'ch_wom', 'gdp_pcap']
data2020.fillna(0, inplace=True)
data2020['pop'] = data2020['pop'].replace({'B': 'e9', 'M': 'e6', 'k': 'e3'}, regex=True).apply(pd.eval)
data2020['gdp_pcap'] = data2020['gdp_pcap'].replace({'k': 'e3'}, regex=True).apply(pd.eval)
data2020.head()
| pop | ch_wom | gdp_pcap | |
|---|---|---|---|
| country | |||
| Afghanistan | 39100000.0 | 5.15 | 1970.0 |
| Angola | 33500000.0 | 5.37 | 6030.0 |
| Albania | 2870000.0 | 1.37 | 13300.0 |
| Andorra | 77400.0 | 1.03 | 49700.0 |
| UAE | 9450000.0 | 1.29 | 67400.0 |
data2020['pop'].isna().sum()
0
import seaborn as sns
sns.set_theme(rc={'figure.figsize':(8,4)})
# Plot miles per gallon against horsepower with other semantics
sns.relplot(x="gdp_pcap", y="ch_wom", size="pop",
sizes=(40, 4000), alpha=.5,
height=6, data=data2020, legend=False)
<seaborn.axisgrid.FacetGrid at 0x7f976ae3ef70>
plt.scatter(x=data2020["gdp_pcap"], y=data2020["ch_wom"],
s=data2020["pop"]/10e5, alpha=0.5)
<matplotlib.collections.PathCollection at 0x7f976aa32a00>
Podemos usar uma inteligência artificial, GitHub Copilot ou Google Gemini, para gerar o código abaixo a partir do terminal (prompt):
gere um gráfico dinâmico com plotly express que mostre a relação entre PIB per capita e filhos por mulher, com o tamanho dos pontos representando a população, para o ano de 2020
import plotly.express as px
import plotly.offline as py
# Select a year for visualization
year = '2020'
# Prepare data for the plot
df = pop[['country', year]].merge(
ch_wom[['country', year]], on='country'
).merge(
gdp_pcap[['country', year]], on='country'
)
df.columns = ['country', 'population', 'children_per_woman', 'gdp_per_capita']
# Convert columns to numeric
df['population'] = df['population'].replace({'B': 'e9', 'M': 'e6', 'k': 'e3'}, regex=True).apply(pd.eval)
df['children_per_woman'] = pd.to_numeric(df['children_per_woman'], errors='coerce')
df['gdp_per_capita'] = df['gdp_per_capita'].replace({'k': 'e3'}, regex=True).apply(pd.eval)
# Create interactive bubble plot
fig = px.scatter(
df,
x='gdp_per_capita',
y='children_per_woman',
size='population',
hover_name='country',
title=f'Bubble Plot for {year}',
labels={
'gdp_per_capita': 'GDP per Capita',
'children_per_woman': 'Children per Woman',
'population': 'Population'
},
size_max=60,
width=800, height=400
)
#fig.show()
py.plot(fig, filename='figure_1.html', auto_open=True)
display(HTML('figure_1.html'))
Usar o seguinte terminal para criar uma animação: “generate the sample plot as above as an annimation by year”
import plotly.express as px
# Prepare data for animation
years = [str(y) for y in range(1960, 2021)] # Use years available in all datasets
# Merge all years into a single dataframe for animation
dfs = []
for y in years:
# Some years may be missing in some countries, so use inner join
temp = pop[['country', y]].merge(
ch_wom[['country', y]], on='country', how='inner'
).merge(
gdp_pcap[['country', y]], on='country', how='inner'
)
temp.columns = ['country', 'population', 'children_per_woman', 'gdp_per_capita']
temp['year'] = y
# Convert columns to numeric
temp['population'] = temp['population'].replace({'B': 'e9', 'M': 'e6', 'k': 'e3'}, regex=True).apply(pd.eval)
temp['children_per_woman'] = pd.to_numeric(temp['children_per_woman'], errors='coerce')
temp['gdp_per_capita'] = temp['gdp_per_capita'].replace({'k': 'e3'}, regex=True).apply(pd.eval)
dfs.append(temp)
df_anim = pd.concat(dfs, ignore_index=True)
# Create animated bubble plot
fig_anim = px.scatter(
df_anim,
x='gdp_per_capita',
y='children_per_woman',
size='population',
hover_name='country',
animation_frame='year',
title='Bubble Plot Animation by Year',
labels={
'gdp_per_capita': 'GDP per Capita',
'children_per_woman': 'Children per Woman',
'population': 'Population'
},
size_max=60
)
py.plot(fig, filename='figure_2.html')
display(HTML('figure_2.html'))
#fig_anim.show()
Prática complementar OPCIONAL#
Bibliografia#
Wilton de Oliveira Bussab and Pedro Alberto Morettin. Estatística básica. Saraiva, 2009.
Kieth A Carlson and Jennifer R Winquist. An introduction to statistics: An active learning approach. Sage Publications, 2017.
Marcos Nascimento Magalhães and Antonio Carlos Pedroso de Lima. Noções de probabilidade e estatística. Volume 5. Editora da Universidade de São Paulo, 2002.
Edson Zangiacomi Martinez. Bioestatística para os cursos de graduação da área da saúde. Blucher São Paulo, 2015.